package com.saascloud.auth.config;

import com.google.common.collect.ImmutableList;
import com.saascloud.auth.core.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.ImportAutoConfiguration;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Primary;
import org.springframework.core.Ordered;
import org.springframework.security.oauth2.provider.expression.OAuth2WebSecurityExpressionHandler;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter;
import org.springframework.security.oauth2.provider.token.store.JwtTokenStore;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.CorsConfigurationSource;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;

/**
 * @Author: liangxu
 * @Contact: one_dream@aliyun.com
 * @Date: 2022/5/23 11:33
 * @Version: 1.0
 * @Description:
 */
@ImportAutoConfiguration({ResouceServerConfig.class, JWTTokenConfig.class})
@EnableConfigurationProperties(OAuthConfig.class)
@Slf4j
public class OauthAutoConfiguration {

    @Autowired
    private OAuthConfig oAuthConfig;

    @Bean
    public CustomAccessDeniedHandler customAccessDeniedHandler() {
        return new CustomAccessDeniedHandler();
    }

    @Bean
    @Primary
    public CustomizedAuthenticationEntryPoint customizedAuthenticationEntryPoint() {
        return new CustomizedAuthenticationEntryPoint();
    }

    @Bean
    public TokenStore tokenStore(JwtAccessTokenConverter jwtAccessTokenConverter) {
        //JWT令牌存储方案
        return new JwtTokenStore(jwtAccessTokenConverter);
    }

    @Bean
    @Primary
    public JwtAccessTokenConverter accessTokenConverter() {
        JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
        //对称秘钥，资源服务器使用该秘钥来验证
        converter.setSigningKey(oAuthConfig.getJwtSecret());
        return converter;
    }

    @Bean
    public MyAuthorityPermit myAuthorityPermit() {
        return new MyAuthorityPermit();
    }

    @Bean
    public TokenEndpoint tokenEndpoint() {
        return new TokenEndpoint();
    }

    /**
     * 动态授权
     */
    @Bean
    public OAuth2WebSecurityExpressionHandler oAuth2WebSecurityExpressionHandler(ApplicationContext applicationContext) {
        OAuth2WebSecurityExpressionHandler expressionHandler = new OAuth2WebSecurityExpressionHandler();
        expressionHandler.setApplicationContext(applicationContext);
        return expressionHandler;
    }

    @Bean
    public CorsConfigurationSource corsConfigurationSource() {
        final CorsConfiguration configuration = new CorsConfiguration();
        configuration.setAllowedOrigins(ImmutableList.of("*"));
        configuration.setAllowedMethods(ImmutableList.of("HEAD",
                "GET", "POST", "PUT", "DELETE", "PATCH"));
        // setAllowCredentials(true) is important, otherwise:
        // The value of the 'Access-Control-Allow-Origin' header in the response must not be the wildcard '*' when the request's credentials mode is 'include'.
        configuration.setAllowCredentials(true);
        // setAllowedHeaders is important! Without it, OPTIONS preflight request
        // will fail with 403 Invalid CORS request
        configuration.setAllowedHeaders(ImmutableList.of("Authorization", "Cache-Control", "Content-Type"));
        final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", configuration);
        return source;
    }

    @Bean
    RemoveBearerHeaderFilter removeBearerHeaderFilter() {
        return new RemoveBearerHeaderFilter();
    }


    @Bean
    public FilterRegistrationBean removeBearerHeaderFilter(RemoveBearerHeaderFilter removeBearerHeaderFilter) {
        FilterRegistrationBean registration = new FilterRegistrationBean(removeBearerHeaderFilter);
        registration.addUrlPatterns("/*");
        registration.setName("headerFilter");
        registration.setOrder(Ordered.HIGHEST_PRECEDENCE);
        return registration;
    }

//    @Bean
//    public ResouceServerConfig resouceServerConfig() {
//        return new ResouceServerConfig();
//    }
}
